jaf.namespace("jaf.launcher");

jaf.launcher.Application = function()   {
   var runtime = jaf.core.Runtime;
   var mBus = jaf.core.MessageBus;
   var Util = jaf.core.Util;
   
   /** The head element of launcher document  */
   var head;
   /** The main workspace iframe of this application launcher  */
   var workspace;
   /** The ids of elements that act as view containers  */
   var viewTargets;
   /** The path of this application */
   var appPath;
   /** The application as module itself */
   var app;

   var views = {};
   
   /**
    * Called when the application module has been successfully initialized, 
    * its module configuration is found, and the module is created.
    * @param {Module} module The module object as defined in the META-INF/jaf-module.js
    */
   function initializeSuccess(module)  {
      app = module;
      /*
      var modDetails = "Module: " + app.id + "\n"
            + "Name: " + app.name + "\n"
            + "BaseURL: " + app.baseUrl + "\n"
            + "Description: " + app.description + "\n"
            + "Version: " + app.version + "\n"
      alert(modDetails);
      */
      
      // make all the view urls absolute 
      var baseUrl = app.baseUrl;
      views = app.views || {};
      for(key in views)   {
         var view = views[key];
         var viewUrl = view.url;
         if(viewUrl)   {
            view.url = resolveUrl(baseUrl, viewUrl);
         }
      }

      // get to know about the modules
      var modules = app.modules;

      if(modules && modules.length > 0)   {
         runtime.loadModules(modules,
            function() {
               // show the start view
               var mainView = views["start"];
               if(mainView) {
                  showViewInElement(workspace, mainView);
               }
            }, 
            function(notLoaded) {
               alert("Following modules were not loaded\n" + notLoaded);
            }
         );
      }
   }
   
   /**
    * Called when there is an error initialization of a module
    */
   function initializeError(modIdOrUrl, error)  {
      alert("Error initializing " + modIdOrUrl + ":=> " + jaf.core.Util.toObjectSource(error));
   }
   
   /**
    * Resolves a base URL of a module with respect to this application
    */
   function resolveUrl(baseUrl, url)   {
      if(! Util.startsWith(url, "/"))  {
         return baseUrl + "/" + url;
      }
      return url;
   }
   
   function showViewInElement(target, objView)  {
      Util.ajax({
         url: objView.url,
         dataType: "text/html",
         onSuccess: function(xhr) {
            var responseText = xhr.responseText;
            // target.style.visibility = "hidden";
            target.innerHTML = responseText;
            var scriptText = "";
            var arrScripts = target.getElementsByTagName("script");
            for(var i = 0, len = arrScripts.length; i < len; i++) {
               var se = arrScripts[i];
               scriptText += se.innerHTML;
            }
            if((scriptText = Util.trim(scriptText)).length != 0)  {
               eval.call(window, scriptText);
            }
            // target.style.visibility = "visible";
         },
         onError: function(xhr, code, message) {
            var responseText = xhr.responseText;
            var content = "<p class='error'>" + responseText + ": " + message + "(" + code + ")</p>"
            workspace.innerHTML = content;
         }
      });
   }
   
   /*
   function showSplash(launchFrame)   {
      var splashInfo = 
      if(! splashInfo)  {
         return;
      }
      
      var doc = launchFrame.document || launchFrame.contentDocument 
            || launchFrame.contentWindow.document;
      var img = doc.getElementById("splash");

      if(img)  {
         img.style.position = "absolute";
         img.style.left = splashInfo.posX + "px";
         img.style.top = splashInfo.posY + "px";
         img.width = splashInfo.width; 
         img.height = splashInfo.height;
         img.src = splashInfo.image;
         img.style.display = "";
      }
   }
   */
   
   // initialize();
   
   return   {
      /**
       * Initializes the application, gets the application path from the URL of this
       * document (launcher) and fetches and loads the main application module
       */
      initialize: function()   {
         // var head = document.getElementsByTagName("head")[0];
         workspace = document.getElementById("workspace");

         appPath = Util.getQuery(document.URL);
         if(!appPath)   {
            alert("Hmm... The application path seems to be wrong. Try something like\n"
               + "http://<hostname>[:<port>]/launcher/launcher.html?/my-application");
            return;
         }
         // load the application module into the runtime
         runtime.loadModule(appPath, initializeSuccess, initializeError);
      },

      /**
       * Imports all the modules in the specified array arrModuleIds and calls successHandler
       * after all the modules have been imported into the current document
       */
      importModules: function(arrModuleIds, successHandler) {
         var arrLibs = [];
         for(var i = 0, len = arrModuleIds.length; i < len; i++)  {
            var m = runtime.getModule(arrModuleIds[i]);
            if(m) {
               var exportInfos = m.exports;
               // resolve the url of all exports
               for(var j = 0, jlen = exportInfos.length; j < jlen; j++)   {
                  var exportInfo = exportInfos[j];
                  
                  if(typeof(exportInfo) === "undefined")  {
                     continue;
                  }
                  
                  if(! Util.startsWith(exportInfo.url, "/"))  {
                     exportInfo.url = m.baseUrl + "/" + exportInfo.url;
                  }
                  
                  // add to the libs to load 
                  arrLibs.push({
                     url: exportInfo.url,
                     type: exportInfo.type,
                     toString: function() {
                        return this.url;
                     }
                  });
               }
            }else {
               alert("Huh? No such module: " + arrModuleIds[i]);
            }
         }
         jaf.core.Loader.load(arrLibs, successHandler);
      },

      importModule: function(moduleId, successHandler, errorHandler) {
         runtime.importModule(moduleId, successHandler, errorHandler);
      },
      
      showView: function(strViewId, elemTarget) {
         if(typeof(elemTarget) == "string")  {
            elemTarget = document.getElementById(elemTarget);
         }
         
         if(!elemTarget) {
            alert("View target not found");
            return;
         }
         
         var v = views[strViewId];
         if(v) {
            showViewInElement(elemTarget, v);
         }else {
            elemTarget.innerHTML = "No such view: " + strViewId;
         }
      }
   };
};

var application = jaf.launcher.Application();
